package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.annotation.DistributedLock;
import com.sc.nft.dao.*;
import com.sc.nft.dto.MetaMapSettleDTO;
import com.sc.nft.dto.UserFirstBuyDTO;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.exception.ModelException;
import com.sc.nft.helper.MessageQueueHelper;
import com.sc.nft.mapper.SecondCollectionMapper;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.util.OrderNoUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.compress.utils.Lists;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class NewSecondCollectionCommonServiceImpl implements NewSecondCollectionCommonService {
    private final Redisson redisson;

    private final RedissonClient redissonClient;

    private final SecondCollectionDao secondCollectionDao;
    private final SecondCollectionMapper secondCollectionMapper;
    private final UserConsensusService userConsensusService;

    private final SecondOrderDao secondOrderDao;

    private final FilterIncomeListService filterIncomeListService;

    private final SecondCollectionConfigDao secondCollectionConfigDao;

    private final DigitalCollectionDao digitalCollectionDao;

    private final UserCollectionDao userCollectionDao;

    private final UserWalletDao userWalletDao;
    private final RedisTemplate redisTemplate;

    private final UserWalletService userWalletService;

    private final UserCollectionService userCollectionService;

    private final MessageQueueHelper messageQueueHelper;

    private final UserInfoDao userInfoDao;

    private final FilterIncomeListDao filterIncomeListDao;

    private final StaticDataService staticDataService;

    private final ExitConsensusUserDao exitConsensusUserDao;

    private final PayOrderItemDao payOrderItemDao;

    private final PayOrderDao payOrderDao;


    @Override
    public List<SecondOrder> getPreTimeOutOrderIds(Date time) {
        return secondOrderDao.getPreTimeOutOrderIds(time);
    }

    @Override
    public BigDecimal selectGoodsTotalPrice(GoodsTotalMoneyDTO goodsTotalMoneyDTO) {
        if (CollUtil.isEmpty(goodsTotalMoneyDTO.getList())) {
            throw new GlobalRunTimeException("请求参数不存在");
        }
        BigDecimal totalMoney = secondCollectionDao.goodsTotalMoney(goodsTotalMoneyDTO.getList());
        return totalMoney != null ? totalMoney.setScale(2, BigDecimal.ROUND_DOWN) : Convert.toBigDecimal("0.00");
    }

    @Override
    public Boolean userBuySumInsufficient(UserInfo userInfo, Long collectionId, Integer sum) {
        if (sum <= 0) {
            throw new ModelException("数量超出限制", ErrorCode.COUNT_NOT_ENOUGH);
        }
        // 藏品配置
        SecondCollectionConfig byCollectionId = secondCollectionConfigDao.getByCollectionId(collectionId);
        if (BeanUtil.isEmpty(byCollectionId)) {
            throw new GlobalRunTimeException("配置不存在");
        }
        if (!byCollectionId.getStatus()) {
            throw new GlobalRunTimeException("配置不存在");
        }
        // 可购买的商品百分比
        Integer buyShares = byCollectionId.getBuyShares();
        // 用户指定id藏品集合
        List<UserCollection> collectionData = userCollectionDao.getByCollectionIdAndUserId(collectionId, userInfo.getId());
        // 这个商品的总库存
        // 可以购买的件数
        // 可购买的数目-已有的藏品数目,是否大于当前要购买的数目
        if (Convert.toInt(Convert.toBigDecimal(buyShares).subtract(Convert.toBigDecimal(collectionData.size()))) >= sum) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }


    /**
     * 锁单,用户下单后把订单上锁,不在给其他用户购买.
     *
     * @param newSecondCollectionLockOrder
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LockOrderVO lockOrder(UserInfo userInfo, NewSecondCollectionLockOrder newSecondCollectionLockOrder) {
        /*
         * 前置条件1:当前用户当天有三笔超时没有支付的订单的话,就不在允许下单
         * 前置条件2:当前余额和当前的商品是否满足支付条件
         * 前置条件3:自己不可以买自己的商品
         * 1.根据售卖id,获取所有的数据.
         * 2.对商品进行循环加锁处理,如果当前商品有锁,则进行下一个商品的加锁,直到加够足够对应的数量,否则抛出异常.
         * 3.商品有足够的数量后写入数据库对订单进行上锁.
         * 4.入库期间,入库成功后,批量释放掉锁.
         * 5.如果期间有锁被占用,则直接抛异常进行回退.不在进行处理.
         * */

        switch (newSecondCollectionLockOrder.getMarketType()) {
            case BRAND_INCUBATION:
//                Map map = startTime(newSecondCollectionLockOrder.getMarketType());
//                Boolean isStart = (Boolean) map.get("isStart");
//                if (!isStart) {
//                    throw new GlobalRunTimeException("当前非市场交易时间段");
//                }
                throw new GlobalRunTimeException("功能已升级，请下载最新版本");
            case FREE_MARKET:
                Map map = startTime(newSecondCollectionLockOrder.getMarketType());
                Boolean isStart = (Boolean) map.get("isStart");
                if (!isStart) {
                    throw new GlobalRunTimeException("当前非市场交易时间段");
                }
                break;
        }
        Long collectionId = newSecondCollectionLockOrder.getCollectionId();
        SecondCollectionConfig byCollectionId = secondCollectionConfigDao.getByCollectionId(collectionId);
        if (BeanUtil.isEmpty(byCollectionId)) {
            throw new GlobalRunTimeException("该藏品暂未上架");
        }
        if (!byCollectionId.getStatus()) {
            throw new GlobalRunTimeException("商品已下架");
        }

        if (newSecondCollectionLockOrder.getMarketType().equals(MarketTypeEnum.BRAND_INCUBATION)) {
            Integer purchasableCount = commodityPurchaseRestriction(userInfo, byCollectionId);
            if (!purchasableCount.equals(-1)) {
                if (newSecondCollectionLockOrder.getSecondCollectionIds().size() > purchasableCount) {
                    throw new GlobalRunTimeException(ErrorCode.PURCHASED_QUANTITY_EXCEEDS_CURRENT_ORDER_QUANTITY);
                }
                if (!userBuySumInsufficient(userInfo, newSecondCollectionLockOrder.getCollectionId(), newSecondCollectionLockOrder.getSecondCollectionIds().size())) {
                    throw new GlobalRunTimeException(ErrorCode.PURCHASED_QUANTITY_EXCEEDS_CURRENT_ORDER_QUANTITY);
                }
            }
        }
        if (getUserOrderExist(userInfo.getId())) {
            throw new GlobalRunTimeException(ErrorCode.WAIT_PAY_ORDER);
        }

        //1.判断是否是市值账号
        FilterIncomeList filterIncomeList = filterIncomeListDao.getIsTeamIncomeByUserId(userInfo.getId());
        if (ObjectUtil.isNotNull(filterIncomeList)) {
            //判断是否是玛特的市值账号
            if (!filterIncomeListDao.checkListIsFilterAccount(Arrays.asList(6L, 7L, 131L, 145L), userInfo.getId())) {
                //如果不是玛特的 则判断市值账号是不是要购买的这个品牌的
                if (!filterIncomeListDao.checkIsFilterAccount(digitalCollectionDao.getById(collectionId).getUserCreatorId(), userInfo.getId())) {
                    throw new GlobalRunTimeException("市值账号只能购买本DAO的藏品");
                }
            }
        }


        LockOrderVO lockOrderVO = new LockOrderVO();
        // 用来装在对应的实体对象数据.
        List<SecondOrder> orders = new ArrayList<>();
        List<Long> mallLockId = new ArrayList<>();
        boolean isConsensus = false;
        DigitalCollection digitalCollection = digitalCollectionDao.getEcologyCollectionById(newSecondCollectionLockOrder.getCollectionId());
        if (ObjectUtil.isNotNull(digitalCollection)) {
            ExitConsensusUser exitConsensusUser = exitConsensusUserDao.getByUserId(userInfo.getId());
            if (ObjectUtil.isNotNull(exitConsensusUser) && exitConsensusUser.getStatus()) {
                isConsensus = false;
            } else {
                isConsensus = true;
            }
        }
        // 开始循环生成订单,生成了订单以后,把数据写到集合里面统一入库.处理期间需要加锁,一旦遇到加锁失败的,直接对他进行回滚,不在入库,直接抛出异常报错
        boolean finalIsConsensus = isConsensus;
        newSecondCollectionLockOrder.getSecondCollectionIds().forEach(aLong -> {
            // 实体对象
            SecondOrder secondOrder = new SecondOrder();
            // 赋值对象
            order(userInfo, aLong, secondOrder, newSecondCollectionLockOrder.getMarketType(), OrderNoUtil.getOrderNo(), mallLockId, finalIsConsensus);
            orders.add(secondOrder);
        });


        if (CollUtil.isNotEmpty(mallLockId)) {
            throw new ModelException(mallLockId, ErrorCode.GOODS_ORDER_LOCK);
        }
        // orders通过表达式获取buyPrice的和
        BigDecimal buyPrice = orders.stream().map(SecondOrder::getBuyPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        lockOrderVO.setMoney(buyPrice);
        // orders通过表达式获取id集合
        List<Long> ids = orders.stream().map(SecondOrder::getId).collect(Collectors.toList());
        lockOrderVO.setOrderIds(ids);
        lockOrderVO.setExpirationTime(DateUtil.offsetMinute(new Date(), 3));
        lockOrderVO.setNowDate(DateTime.now());
        updateCacheMinPrice(collectionId);
        return lockOrderVO;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public LockOrderVO lockBrandOrder(UserInfo userInfo, Long collectionId, List<Long> secondCollectionIds) {

        if (getUserOrderExist(userInfo.getId())) {
            throw new GlobalRunTimeException(ErrorCode.WAIT_PAY_ORDER);
        }

        LockOrderVO lockOrderVO = new LockOrderVO();
        // 开始循环生成订单,生成了订单以后,把数据写到集合里面统一入库.处理期间需要加锁,一旦遇到加锁失败的,直接对他进行回滚,不在入库,直接抛出异常报错
        DigitalCollection digitalCollection = digitalCollectionDao.getById(collectionId);
        DateTime now = DateTime.now();
        lockOrderVO.setNowDate(now);
        lockOrderVO.setExpirationTime(DateUtil.offsetMinute(now, 3));
        lockOrderVO.setOrderList(Lists.newArrayList());
        secondCollectionIds.forEach(secondCollectionId ->
        {
            orderBrand(userInfo, secondCollectionId, digitalCollection, lockOrderVO);
        });
        if (CollUtil.isEmpty(lockOrderVO.getOrderIds())) {
            throw new GlobalRunTimeException("尝试锁单失败，请重试");
        }
        return lockOrderVO;
    }


    @Override
    public CollectionBuyConfirmVO collectionBuyConfirm(UserInfo userInfo, CollectionBuyConfirmDTO collectionBuyConfirmDTO) {
        CollectionBuyConfirmVO collectionBuyConfirmVO = new CollectionBuyConfirmVO();

        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionIdAndMarketType(collectionBuyConfirmDTO.getCollectionId(), MarketTypeEnum.getMarketTypeEnum(collectionBuyConfirmDTO.getMarketType()));
        if (BeanUtil.isEmpty(secondCollectionConfig)) {
            throw new GlobalRunTimeException("市场藏品不存在");
        }
        collectionBuyConfirmVO.setPresentPrice(secondCollectionConfig.getMaxPrice());
        DigitalCollection digitalCollection = digitalCollectionDao.getById(collectionBuyConfirmDTO.getCollectionId());
        if (BeanUtil.isEmpty(digitalCollection)) {
            throw new GlobalRunTimeException("市场藏品不存在");
        }
        collectionBuyConfirmVO.setTitle(digitalCollection.getFirstTitle());
        collectionBuyConfirmVO.setPublishPrice(digitalCollection.getIssuePrice());
        // 搜索当前挂单的数据
        Integer presentCount = secondCollectionDao.presentCount(userInfo, collectionBuyConfirmDTO.getCollectionId(), getMaxId());
        collectionBuyConfirmVO.setPresentOrder(presentCount);
        // 可买数量
        if (collectionBuyConfirmDTO.getMarketType().equals(1)) {
            Integer commodityPurchaseRestriction = commodityPurchaseRestriction(userInfo, secondCollectionConfig);
            if (!commodityPurchaseRestriction.equals(-1)) {
                if (commodityPurchaseRestriction > 0) {
                    collectionBuyConfirmVO.setPurchasable(commodityPurchaseRestriction > presentCount ? presentCount : commodityPurchaseRestriction);
                } else {
                    collectionBuyConfirmVO.setPurchasable(0);
                }
            } else {
                collectionBuyConfirmVO.setPurchasable(999);
            }
        }

        // 钱包余额
        UserWallet userWallet = userWalletDao.getByUserId(userInfo.getId());
        if (BeanUtil.isEmpty(userWallet)) {
            throw new GlobalRunTimeException("用户不存在");
        }
        collectionBuyConfirmVO.setBalanceWallet(userWallet.getBalance().add(userWallet.getPayBalance()));
        // 求当前购买全部总额度
//        SecondCollection secondCollection = secondCollectionDao.presentSum(collectionBuyConfirmDTO.getCollectionId());
//        if (!BeanUtil.isEmpty(secondCollection)) {
//            collectionBuyConfirmVO.setAggregate(secondCollection.getSalesPrice() != null ? secondCollection.getSalesPrice() : Convert.toBigDecimal(0));
//        } else {
        collectionBuyConfirmVO.setAggregate(BigDecimal.ZERO);
//        }
        return collectionBuyConfirmVO;
    }

    @Override
    public List<NewSecondCollectionGoodsBuyListVO> newSecondCollectionGoodsBuyList(UserInfo userInfo, NewSecondCollectionGoodsBuyListDTO newSecondCollectionGoodsBuyListDTO) {
        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionId(newSecondCollectionGoodsBuyListDTO.getCollectionId());
        if (newSecondCollectionGoodsBuyListDTO.getMarketType().equals(MarketTypeEnum.BRAND_INCUBATION)) {
            Integer purchasableCount = commodityPurchaseRestriction(userInfo, secondCollectionConfig);
            if (!purchasableCount.equals(-1)) {
                if (newSecondCollectionGoodsBuyListDTO.getSum() > purchasableCount) {
                    throw new GlobalRunTimeException("购买数量不合法");
                }
            }
        }
        FilterIncomeList byUserId = filterIncomeListDao.getByUserId(userInfo.getId());
        // 是否为市值账号,如果是市值账号,最大可以买200个.如果不是的话.最大购买值为配置的值
        Integer buyShares = 0;
        if (BeanUtil.isNotEmpty(byUserId)) {
            buyShares = 200;
        } else {
            buyShares = secondCollectionConfig.getBuyShares();
        }
        List<Long> range = redisTemplate.opsForList().range(RedisKeyEnum.SECOND_SALES_COLLECTION.getKey() + newSecondCollectionGoodsBuyListDTO.getCollectionId().toString(), 0, buyShares - 1);
        if (CollUtil.isNotEmpty(range)) {
            return secondOrderDao.selectNewSecondCollectionGoodsBuyIds(newSecondCollectionGoodsBuyListDTO.getCollectionId(), range, userInfo.getId(), newSecondCollectionGoodsBuyListDTO.getSum(), getMaxId());
        }
        return secondOrderDao.selectNewSecondCollectionGoodsBuyList(userInfo, newSecondCollectionGoodsBuyListDTO, getMaxId());
    }

    @Override
    public List<Long> getBrandSecondCollectionIdsWithCache(SecondCollectionConfig collectionConfig, UserInfo userInfo, Long collectionId, Integer count) {
        if (collectionConfig.getMarketType() == MarketTypeEnum.BRAND_INCUBATION) {
            Integer purchasableCount = commodityPurchaseRestriction(userInfo, collectionConfig);
            if (!purchasableCount.equals(-1)) {
                if (count > purchasableCount) {
                    throw new GlobalRunTimeException("购买数量超出限制");
                }
            }
        } else {
            throw new GlobalRunTimeException("该功能已升级，请下载最新版本");
        }
        List<String> selfCollectionIds = Lists.newArrayList();
        List<Long> secondCollectionIds = Lists.newArrayList();
        for (Integer i = 0; i < count; i++) {
            Object o = redisTemplate.opsForList().leftPop(RedisKeyEnum.SECOND_SALES_COLLECTION.getKey() + collectionId.toString());
            if (ObjectUtil.isNotNull(o)) {
                Long secondCollectionId = NumberUtil.parseLong(String.valueOf(o));
                if (secondCollectionDao.checkSelfSalesCollection(secondCollectionId, userInfo.getId())) {
                    i--;
                    selfCollectionIds.add(secondCollectionId.toString());
                } else {
                    secondCollectionIds.add(secondCollectionId);
                }
            } else {
                break;
            }
        }
        if (CollUtil.isNotEmpty(selfCollectionIds)) {
            backSalesCollection(collectionId, selfCollectionIds);
        }
        return secondCollectionIds;
    }


    @Override
    public List<Long> getBrandSecondCollectionIdsWithDB(SecondCollectionConfig collectionConfig, UserInfo userInfo, Long collectionId, Integer count) {
        if (collectionConfig.getMarketType() == MarketTypeEnum.BRAND_INCUBATION) {
            Integer purchasableCount = commodityPurchaseRestriction(userInfo, collectionConfig);
            if (!purchasableCount.equals(-1)) {
                if (count > purchasableCount) {
                    throw new GlobalRunTimeException("购买数量超出限制");
                }
            }
        }
        return secondCollectionDao.getByOnSalesIdWithOutSelf(collectionConfig.getMarketType(), collectionId, userInfo.getId(), getMaxId(), count);

    }

    @Override
    public void backSalesCollection(Long collectionId, List<String> secondCollectionIds) {
        redisTemplate.opsForList().leftPushAll(RedisKeyEnum.SECOND_SALES_COLLECTION.getKey() + collectionId.toString(), secondCollectionIds);
    }


    @Override
    public void cacheMaxId() {
        Long maxId = secondCollectionDao.getMaxId();
        redisTemplate.opsForValue().set(RedisKeyEnum.SECOND_MAX_ID.getKey(), maxId.toString(), 18, TimeUnit.HOURS);
    }

    private Long getMaxId() {
        Long maxId = null;
        Object o = redisTemplate.opsForValue().get(RedisKeyEnum.SECOND_MAX_ID.getKey());
        if (ObjectUtil.isNull(o)) {
            maxId = secondCollectionDao.getYesterdayMaxId();
            redisTemplate.opsForValue().set(RedisKeyEnum.SECOND_MAX_ID.getKey(), maxId.toString(), 18, TimeUnit.HOURS);
        } else {
            maxId = Long.parseLong(o.toString());
        }
        return maxId;
    }

    @Override
    public Page<NewSecondCollectionGoodsBuyOrderListVO> selectNewSecondCollectionGoodsSaleOrderList(NewSecondCollectionGoodsBuyOrderListDTO newSecondCollectionGoodsBuyOrderListDTO) {
        return secondOrderDao.selectNewSecondCollectionGoodsSaleOrderList(newSecondCollectionGoodsBuyOrderListDTO);
    }

    @Override
    public Page<NewSecondCollectionGoodsBuyOrderListVO> selectNewSecondCollectionGoodsBuyOrderList(NewSecondCollectionGoodsBuyOrderListDTO newSecondCollectionGoodsBuyOrderListDTO) {
        return secondOrderDao.selectNewSecondCollectionGoodsBuyOrderList(newSecondCollectionGoodsBuyOrderListDTO);
    }

    @Override
    public Page<NewSecondCollectionGoodsBuyOrderListVO> overdueOrderList(UserInfo user, Page page) {
        return secondOrderDao.overdueOrderList(page, user.getId());
    }

    @Override
    public SecondOverdueOrderDetailsVO overdueOrderDetails(Long orderId, Long userId) {
        return secondOrderDao.overdueOrderDetails(orderId, userId);
    }

    @Override
    public NewSecondCollectionNotPayVO newSecondCollectionNotPay() {
        // 获取最新一条订单藏品的id,页面只展示当前下订单最新的一条
        SecondOrder userInfoNewOrder = secondOrderDao.getUserInfoNewOrder();
        if (BeanUtil.isEmpty(userInfoNewOrder)) {
            throw new GlobalRunTimeException("当前不存在未付款订单");
        }
        // 根据这一条数据的藏品id.获取用户当前这个藏品数据的最新内容
        // 藏品id
        Long collectionId = userInfoNewOrder.getCollectionId();
        DigitalCollection digitalCollection = digitalCollectionDao.getById(collectionId);
        NewSecondCollectionNotPayVO newSecondCollectionNotPayVO = new NewSecondCollectionNotPayVO();
        newSecondCollectionNotPayVO.setFirstTitle(digitalCollection.getFirstTitle());
        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionId(collectionId);
        if (BeanUtil.isEmpty(secondCollectionConfig)) {
            throw new GlobalRunTimeException("配置不存在");
        }
        if (!secondCollectionConfig.getStatus()) {
            throw new GlobalRunTimeException("配置不存在");
        }
        newSecondCollectionNotPayVO.setBuyPrice(secondCollectionConfig.getMaxPrice());
        newSecondCollectionNotPayVO.setCreationContent(digitalCollection.getCreationContent());
        // 获取对应id的数据
        List<NewSecondCollectionNotPayOrderVO> newSecondCollectionNotPayOrder = secondOrderDao.getNewSecondCollectionNotPayOrder(collectionId);
        // newSecondCollectionNotPayOrder获取dealTime最早的一条数据
        if (CollUtil.isNotEmpty(newSecondCollectionNotPayOrder)) {
            newSecondCollectionNotPayOrder.sort(Comparator.comparing(NewSecondCollectionNotPayOrderVO::getDealTime));
            newSecondCollectionNotPayVO.setDealTime(newSecondCollectionNotPayOrder.get(0).getDealTime());
            // newSecondCollectionNotPayOrder.get(0).getDealTime()时间+3分钟,让后用增加过后的时间,-当前时间,得到剩余时间,结果取秒
            newSecondCollectionNotPayVO.setExpirationTime(DateUtil.offsetMinute(newSecondCollectionNotPayOrder.get(0).getDealTime(), 3));
        }
        newSecondCollectionNotPayVO.setData(newSecondCollectionNotPayOrder);
        newSecondCollectionNotPayVO.setNowDate(DateUtil.now());
        if (CollUtil.isEmpty(newSecondCollectionNotPayOrder)) {
            throw new GlobalRunTimeException("当前不存在未付款订单");
        }
        return newSecondCollectionNotPayVO;
    }

    @Override
    public NewSecondCollectionOrderDetailsVO nweSecondCollectionOrderDetails(Long orderId) {
        //TODO 这里要保存付款方式 6.36-pay
        NewSecondCollectionOrderDetailsVO newSecondCollectionOrderDetailsVO = secondOrderDao.nweSecondCollectionOrderDetails(orderId);
        if(OrderStatusEnum.PAYMENT.equals(newSecondCollectionOrderDetailsVO.getStatus())){
            PayOrder payOrder = payOrderItemDao.getByOrderIdAndType(orderId,
                    SecondPayOrderItemTypeEnum.COLLECTION, PayTypeEnum.SECOND);
            newSecondCollectionOrderDetailsVO.setPayType(payOrder.getPayType());
            newSecondCollectionOrderDetailsVO.setPayIcon(null != payOrder.getPayType() ? payOrder.getPayType().getIcon() : null);
        }
        newSecondCollectionOrderDetailsVO.setNowDate(DateUtil.now());
        newSecondCollectionOrderDetailsVO.setExpirationTime(DateUtil.offsetMinute(DateUtil.parse(newSecondCollectionOrderDetailsVO.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), 3));
        return newSecondCollectionOrderDetailsVO;
    }

    @Override
    public NewSecondCollectionOrderDetailsVO nweSecondCollectionOrderSaleDetails(Long orderId) {
        //TODO 这里要保存收款方式 6.36-pay
        NewSecondCollectionOrderDetailsVO newSecondCollectionOrderDetailsVO = secondOrderDao.nweSecondCollectionOrderSaleDetails(orderId);

        newSecondCollectionOrderDetailsVO.setReceiveIcon(null != newSecondCollectionOrderDetailsVO.getReceiveType() ?
                newSecondCollectionOrderDetailsVO.getReceiveType().getIcon() : null);
        newSecondCollectionOrderDetailsVO.setNowDate(DateUtil.now());
        newSecondCollectionOrderDetailsVO.setExpirationTime(DateUtil.offsetMinute(DateUtil.parse(newSecondCollectionOrderDetailsVO.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), 3));
        return newSecondCollectionOrderDetailsVO;
    }

    @Override
    public GetUserItemStatusVO getUserItemStatus(GetUserItemStatusDTO getUserItemStatusDTO) {
        GetUserItemStatusVO getUserItemStatusVO = new GetUserItemStatusVO();

        // 根据用户藏品id获取数据,判定该藏品是否可以出售.如果可以则判定该藏品是否正在出售,如果正在出售.
        UserCollection userCollection = userCollectionDao.selectByIdAndUserId(getUserItemStatusDTO.getSecondCollectionId(), UserPool.getUser().getId());
        if (BeanUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException("藏品不存在");
        }
        // 藏品id
        Long collectionId = userCollection.getCollectionId();
        // 用户藏品id
        Long userCollectionId = userCollection.getId();
        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionId(collectionId);
        if (BeanUtil.isEmpty(secondCollectionConfig) || !secondCollectionConfig.getStatus()) {
            getUserItemStatusVO.setStatus(0);
            return getUserItemStatusVO;
        }
        // 不为空判断是否当前藏品正在出售
        SecondCollection secondCollection = secondCollectionDao.selectByUserCollectionIdAndUserId(userCollectionId, UserPool.getUser().getId());
        if (BeanUtil.isEmpty(secondCollection)) {
            getUserItemStatusVO.setStatus(1);
            return getUserItemStatusVO;
        }
        if (secondCollection.getStatus() == ConSignStatus.ON_SALES || secondCollection.getStatus() == ConSignStatus.LOCK) {
            getUserItemStatusVO.setStatus(2);
        } else {
            getUserItemStatusVO.setStatus(1);
        }
        return getUserItemStatusVO;
    }

    @Override
    public GetUserConsignmentVO getUserConsignment(GetUserConsignmentDTO getUserConsignmentDTO) {
        GetUserConsignmentVO getUserConsignmentVO = new GetUserConsignmentVO();
        // 用户藏品
        UserCollection userCollection = userCollectionDao.getById(getUserConsignmentDTO.getSecondCollectionId());
        if (BeanUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException("数据不存在");
        }
        if (userCollection.getIsDelete().equals(1)) {
            throw new GlobalRunTimeException("数据不存在");
        }
        // 藏品配置
        SecondCollectionConfig byCollectionId = secondCollectionConfigDao.getByCollectionId(userCollection.getCollectionId());
        if (BeanUtil.isEmpty(byCollectionId)) {
            throw new GlobalRunTimeException("藏品禁止上架");
        }
        if (!byCollectionId.getStatus()) {
            throw new GlobalRunTimeException("藏品禁止上架");
        }
        // 向下涨幅
        BigDecimal freeDownRatio = byCollectionId.getFreeDownRatio();
        // 向上涨幅
        BigDecimal freeUpRatio = byCollectionId.getFreeUpRatio();
        // 历史价格,浮动价格
        BigDecimal floatingPrice = byCollectionId.getFloatingPrice();
        if (floatingPrice.compareTo(BigDecimal.ZERO) >= 0) {
            // 拿当天第一笔数据,拿的到的话就把值覆盖掉,找不到的话就不做处理
            SecondOrder secondOrder = secondOrderDao.toDayOrderLimitOneAsc();
            if (!BeanUtil.isEmpty(secondOrder)) {
                floatingPrice = secondOrder.getBuyPrice();
            }
        }
        // 如果等于0的话证明第一单,随便他发布.价格随意
        if (floatingPrice.compareTo(Convert.toBigDecimal(0)) == 0) {
            getUserConsignmentVO.setMinPrice(Convert.toBigDecimal("0"));
            getUserConsignmentVO.setMaxPrice(Convert.toBigDecimal("0"));
        } else if (floatingPrice.compareTo(Convert.toBigDecimal(0)) == 1) {
            freeDownRatio = (Convert.toBigDecimal(100).subtract(freeDownRatio)).divide(Convert.toBigDecimal(100), 2, BigDecimal.ROUND_DOWN);
            freeUpRatio = (Convert.toBigDecimal(100).add(freeUpRatio)).divide(Convert.toBigDecimal(100), 2, BigDecimal.ROUND_DOWN);
            getUserConsignmentVO.setMinPrice(freeDownRatio.multiply(floatingPrice));
            getUserConsignmentVO.setMaxPrice(freeUpRatio.multiply(floatingPrice));
        }
        DigitalCollection digitalCollection = digitalCollectionDao.getById(byCollectionId);
        getUserConsignmentVO.setSalePrice(digitalCollection.getIssuePrice());
        getUserConsignmentVO.setLatestPrice(floatingPrice);
        getUserConsignmentVO.setFirstTitle(digitalCollection.getFirstTitle());
        getUserConsignmentVO.setCreationContent(digitalCollection.getCreationContent());
        return getUserConsignmentVO;
    }

    private BigDecimal freeMarketHistoricalMaximumAmount(Long collectionId) {
        BigDecimal maxId = BigDecimal.ZERO;
        String key = StrUtil.format(RedisKeyEnum.FREE_MARKET_HISTORICAL_MAXIMUM_AMOUNT.getKey(), collectionId);
        Object o = redisTemplate.opsForValue().get(key);
        if (ObjectUtil.isNull(o)) {
            maxId = secondOrderDao.getMaxPriceByCollectionId(collectionId);
            if (maxId == null) {
                maxId = BigDecimal.ZERO;
            }
            // 当前时间到第二天零点的秒数
            DateTime now = DateTime.now();
            long seconds = DateUtil.between(now, DateUtil.endOfDay(now), DateUnit.SECOND);
            redisTemplate.opsForValue().set(key, maxId.toString(), seconds, TimeUnit.SECONDS);
        } else {
            maxId = Convert.toBigDecimal(o.toString());
        }
        return maxId;
    }


    @Override
    public UserConsignmentCollectionPriceVO getUserConsignmentCollectionPrice(UserConsignmentCollectionPriceDTO userConsignmentCollectionPriceDTO) {
        UserConsignmentCollectionPriceVO userConsignmentCollectionPriceVO = new UserConsignmentCollectionPriceVO();
        if (userConsignmentCollectionPriceDTO.getPrice() == null || userConsignmentCollectionPriceDTO.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new GlobalRunTimeException("额度错误");
        }
        UserCollection byId = userCollectionDao.selectByIdAndUserId(userConsignmentCollectionPriceDTO.getSecondCollectionId(), UserPool.getUser().getId());
        if (BeanUtil.isEmpty(byId)) {
            throw new GlobalRunTimeException("数据不存在");
        }
        if (byId.getIsDelete().equals(1)) {
            throw new GlobalRunTimeException("数据不存在");
        }
        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionId(byId.getCollectionId());
        if (BeanUtil.isEmpty(secondCollectionConfig)) {
            throw new GlobalRunTimeException("藏品禁止上架");
        }
        if (!secondCollectionConfig.getStatus()) {
            throw new GlobalRunTimeException("藏品禁止上架");
        }

        // 向下涨幅
//        BigDecimal freeDownRatio = secondCollectionConfig.getFreeDownRatio();
//        // 向上涨幅
//        BigDecimal freeUpRatio = secondCollectionConfig.getFreeUpRatio();
//        // 历史价格,浮动价格
//        BigDecimal floatingPrice = secondCollectionConfig.getFloatingPrice();

//        freeDownRatio = (Convert.toBigDecimal(100).subtract(freeDownRatio)).divide(Convert.toBigDecimal(100), 2, BigDecimal.ROUND_DOWN);
//        freeUpRatio = (Convert.toBigDecimal(100).add(freeUpRatio)).divide(Convert.toBigDecimal(100), 2, BigDecimal.ROUND_DOWN);

        if (secondCollectionConfig.getFloatingPrice().compareTo(Convert.toBigDecimal(0)) == -1) {
            if (secondCollectionConfig.getMinPrice().compareTo(userConsignmentCollectionPriceDTO.getPrice()) != 1 && secondCollectionConfig.getMaxPrice().compareTo(userConsignmentCollectionPriceDTO.getPrice()) != -1) {
                throw new GlobalRunTimeException("寄售价格超出区间");
            }
        }
        BigDecimal charge = secondCollectionConfig.getCharge();
        userConsignmentCollectionPriceVO.setPrice(userConsignmentCollectionPriceDTO.getPrice().subtract(userConsignmentCollectionPriceDTO.getPrice().multiply(charge)).subtract(secondCollectionConfig.getGas()));
        userConsignmentCollectionPriceVO.setCharge(userConsignmentCollectionPriceDTO.getPrice().multiply(charge));
        userConsignmentCollectionPriceVO.setGas(secondCollectionConfig.getGas());
        return userConsignmentCollectionPriceVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancellationConsignment(CancellationConsignmentDTO cancellationConsignmentDTO) {
        if (!UserPool.getUser().getTransactionPassword().equals(cancellationConsignmentDTO.getDealPwd())) {
            throw new GlobalRunTimeException("支付密码错误");
        }
        String key = StrUtil.format("LOCK_ORDER:{}", cancellationConsignmentDTO.getId());
        RLock orderLock = redissonClient.getLock(key);
        boolean heldByCurrentThread = orderLock.tryLock();
        if (!heldByCurrentThread) {
            // 把挂载的商品id返回去.
            throw new ModelException(cancellationConsignmentDTO.getId(), ErrorCode.COLLECTION_NOT_FOUND);
        }
        try {
            SecondCollection secondCollection = secondCollectionDao.selectByUserCollectionIdAndUserId(cancellationConsignmentDTO.getId(), UserPool.getUser().getId());
            if (ObjectUtil.isNull(secondCollection)) {
                throw new GlobalRunTimeException("未找到藏品寄售记录");
            }

            if (secondCollection.getStatus() == ConSignStatus.LOCK) {
                throw new GlobalRunTimeException("该藏品已被锁定，无法取消");
            }
            if (secondCollection.getStatus() == ConSignStatus.SUCCESS) {
                throw new GlobalRunTimeException("藏品已售出");
            }

            userCollectionDao.setConsignStatus(secondCollection.getUserCollectionId(), CollectionOnConsignEnum.NORMAL);
            Boolean collectionSoldOutBoolean = secondCollectionDao.collectionSoldOut(secondCollection.getId());
            Assert.isTrue(collectionSoldOutBoolean, () -> new GlobalRunTimeException("藏品取消失败,请刷新后重试"));
            if (secondCollection.getMarketType() == MarketTypeEnum.BRAND_INCUBATION) {
                redisTemplate.opsForList().remove(RedisKeyEnum.SECOND_SALES_COLLECTION.getKey() + secondCollection.getCollectionId().toString(), 1, secondCollection.getId().toString());
            }
            updateCacheMinPrice(secondCollection.getCollectionId());
            DigitalCollection digitalCollection = digitalCollectionDao.getEcologyCollectionById(secondCollection.getCollectionId());
            if (ObjectUtil.isNotNull(digitalCollection)) {
                userConsensusService.adjustConsensusService(UserPool.getUser().getId(), digitalCollection.getId(), BigDecimal.ONE, UserConsensusTypeEnums.CANCEL, digitalCollection.getFirstTitle(), null);
                redisTemplate.opsForValue().set(RedisKeyEnum.CONSENSUS_CONSIGN_LOCK.getKey() + UserPool.getUser().getId().toString(), "1", 30, TimeUnit.MINUTES);
            }
            return collectionSoldOutBoolean;
        } finally {
            orderLock.unlock();
        }
    }

    /**
     * 自由市场上架
     *
     * @param userCollectionId
     * @param buyPrice
     * @param dealPwd
     * @return
     */
    @Override
    @DistributedLock(value = {"freeMarketHitShelf", "#{userCollectionId}"}, message = "藏品上架中")
    @Transactional(rollbackFor = Exception.class)
    public Boolean freeMarketHitShelf(Long userCollectionId, BigDecimal buyPrice, String dealPwd) {
        if (!UserPool.getUser().getIsValid()) {
            throw new GlobalRunTimeException("不满足寄售条件");
        }
        if (!UserPool.getUser().getTransactionPassword().equals(dealPwd)) {
            throw new GlobalRunTimeException("支付密码错误");
        }

        // 用户要上架的藏品
        UserCollection userCollection = userCollectionDao.selectByIdAndUserIdAndIsHold(userCollectionId, UserPool.getUser().getId());
        if (ObjectUtil.isNull(userCollection)) {
            throw new GlobalRunTimeException("未找到藏品");
        }
        DigitalCollection digitalCollection = digitalCollectionDao.getById(userCollection.getCollectionId());
        if (ObjectUtil.isNull(digitalCollection)) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        if (digitalCollection.getCollectionType() == DigitalMarketTypeEnum.ECOLOGY) {
            ExitConsensusUser exitConsensusUser = exitConsensusUserDao.getByUserId(UserPool.getUser().getId());
            if (ObjectUtil.isNotNull(exitConsensusUser) && exitConsensusUser.getStatus()) {

            } else {
                userConsensusService.adjustConsensusService(UserPool.getUser().getId(), digitalCollection.getId(), BigDecimal.ONE.negate(), UserConsensusTypeEnums.SELL, userCollection.getFirstTitle(), null);
            }

        }

        // 锁仓中藏品
        if (userCollection.getLockedPositionTime() != null && userCollection.getLockedPositionTime().after(DateUtil.date())) {
            throw new GlobalRunTimeException(ErrorCode.LOCK_COLLECTION);
        }

        if (userCollection.getOnConsign() != CollectionOnConsignEnum.NORMAL) {
            throw new GlobalRunTimeException("该藏品正在寄售");
        }
        if (userCollection.getIsSmeltingOnly()) {
            throw new GlobalRunTimeException(ErrorCode.IS_SMELTING_ONLY);
        }
        UserCollectionFreezingStatusEnum freezingStatus = userCollection.getFreezingStatus();
        if (!freezingStatus.equals(UserCollectionFreezingStatusEnum.NORMAL)) {
            if (freezingStatus == UserCollectionFreezingStatusEnum.OPEN_SHOP) {
                throw new GlobalRunTimeException("该藏品已开启店铺，无法上架");
            } else if (freezingStatus == UserCollectionFreezingStatusEnum.LOCK) {
                throw new GlobalRunTimeException("该藏品正在进行拍卖活动,无法上架");
            } else {
                throw new GlobalRunTimeException("该藏品正在进行秘境活动,无法上架");
            }
        }
        if (BeanUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException("藏品不存在");
        }
        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionId(userCollection.getCollectionId());
        // 如果去了的价格卖了以后钱是负数,那么不允许上架
        if (NumberUtil.isLessOrEqual(buyPrice.subtract(buyPrice.multiply(secondCollectionConfig.getCharge())).subtract(secondCollectionConfig.getGas()), BigDecimal.ZERO)) {
            throw new GlobalRunTimeException("该价格过低无法上架");
        }
        if (secondCollectionConfig.getMarketType().equals(MarketTypeEnum.BRAND_INCUBATION)) {
            //获取寄售时间 并且判断是否是在寄售时间内
            StaticData staticData = staticDataService.getByType("market_config");
            if (ObjectUtil.isNull(staticData) || StrUtil.isBlank(staticData.getValue())) {
                throw new GlobalRunTimeException(ErrorCode.NOT_ALLOW_DEAL_TIME);
            }
            DateTime now = DateTime.now();
            String dateStr = now.toString("yyyy-MM-dd");
            MarketConfigDTO marketConfigDTO = JSONObject.parseObject(staticData.getValue(), MarketConfigDTO.class);
            DateTime billingStartDate1 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingStartTimeOne(), "yyyy-MM-dd HH:mm");
            DateTime billingEndDate1 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingEndTimeOne(), "yyyy-MM-dd HH:mm");
            DateTime billingStartDate2 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingStartTimeTwo(), "yyyy-MM-dd HH:mm");
            DateTime billingEndDate2 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingEndTimeTwo(), "yyyy-MM-dd HH:mm");

            if (!((now.after(billingStartDate1) && now.before(billingEndDate1)) || (now.after(billingStartDate2) && now.before(billingEndDate2)))) {
                throw new GlobalRunTimeException(ErrorCode.NOT_ALLOW_DEAL_TIME);
            }
        } else if (secondCollectionConfig.getMarketType().equals(MarketTypeEnum.FREE_MARKET)) {
            StaticData staticData = staticDataService.getByType("free_market_config");
            if (ObjectUtil.isNull(staticData) || StrUtil.isBlank(staticData.getValue())) {
                throw new GlobalRunTimeException(ErrorCode.NOT_ALLOW_DEAL_TIME);
            }
            DateTime now = DateTime.now();
            String dateStr = now.toString("yyyy-MM-dd");
            MarketConfigDTO marketConfigDTO = JSONObject.parseObject(staticData.getValue(), MarketConfigDTO.class);
            DateTime billingStartDate1 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingStartTimeOne(), "yyyy-MM-dd HH:mm");
            DateTime billingEndDate1 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingEndTimeOne(), "yyyy-MM-dd HH:mm");
            DateTime billingStartDate2 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingStartTimeTwo(), "yyyy-MM-dd HH:mm");
            DateTime billingEndDate2 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBillingEndTimeTwo(), "yyyy-MM-dd HH:mm");
            if (!((now.after(billingStartDate1) && now.before(billingEndDate1)) || (now.after(billingStartDate2) && now.before(billingEndDate2)))) {
                throw new GlobalRunTimeException(ErrorCode.NOT_ALLOW_DEAL_TIME);
            }
        }
        if (BeanUtil.isEmpty(secondCollectionConfig) || !secondCollectionConfig.getStatus()) {
            throw new GlobalRunTimeException("藏品禁止上架");
        }

        //查询当前藏品是否是寄售状态
        if (BeanUtil.isNotEmpty(secondCollectionDao.getOnShelfUserCollectionId(userCollectionId))) {
            throw new GlobalRunTimeException(ErrorCode.ON_CON_SIGN);
        }
        // 获取排除今天的历史最高价.
//        BigDecimal maxPriceByCollectionId = freeMarketHistoricalMaximumAmount(secondCollectionConfig.getCollectionId());
// maxPriceByCollectionId历史最大值如果为空 那么startPrice=startPrice  如果不为空 ,那么判定maxPriceByCollectionId>startPrice 那么startPrice=maxPriceByCollectionId
//        BigDecimal floatingPrice = maxPriceByCollectionId == null ? secondCollectionConfig.getStartPrice() : maxPriceByCollectionId.compareTo(secondCollectionConfig.getStartPrice()) == 1 ? maxPriceByCollectionId : secondCollectionConfig.getStartPrice();
        if (MarketTypeEnum.BRAND_INCUBATION.equals(secondCollectionConfig.getMarketType())) {
            //如果藏品价格大于0
            if (secondCollectionConfig.getStartPrice().compareTo(BigDecimal.ZERO) > 0) {
                //判断传入价格 是否在可寄售的价格区间内
                if (!(secondCollectionConfig.getMinPrice().compareTo(buyPrice) <= 0 &&
                        secondCollectionConfig.getMaxPrice().compareTo(buyPrice) >= 0)) {
                    throw new GlobalRunTimeException(ErrorCode.CON_SIGN_PRICE_ERROR);
                }
            }
        } else {
            if (digitalCollection.getCollectionType() == DigitalMarketTypeEnum.ECOLOGY) {
                ExitConsensusUser exitConsensusUser = exitConsensusUserDao.getByUserId(UserPool.getUser().getId());
                if (ObjectUtil.isNotNull(exitConsensusUser) && exitConsensusUser.getStatus()) {
                    if (NumberUtil.isLess(buyPrice, secondCollectionConfig.getMinPrice()) || NumberUtil.isGreater(buyPrice, secondCollectionConfig.getMaxPrice())) {
                        throw new GlobalRunTimeException("请在可挂售区间内出价");
                    }
                } else {
                    if (NumberUtil.isLess(buyPrice, secondCollectionConfig.getConsensusMinPrice()) || NumberUtil.isGreater(buyPrice, secondCollectionConfig.getConsensusMaxPrice())) {
                        throw new GlobalRunTimeException("请在可挂售区间内出价");
                    }
                }

            } else {
                if (NumberUtil.isLess(buyPrice, secondCollectionConfig.getMinPrice()) || NumberUtil.isGreater(buyPrice, secondCollectionConfig.getMaxPrice())) {
                    throw new GlobalRunTimeException("请在可挂售区间内出价");
                }
            }

        }


        SecondCollection secondCollection = new SecondCollection();
        secondCollection.setCollectionId(userCollection.getCollectionId());
        secondCollection.setUserCollectionId(userCollection.getId());
        secondCollection.setUserId(UserPool.getUser().getId());
        secondCollection.setStatus(ConSignStatus.ON_SALES);
        secondCollection.setOnShelfTime(new Date());
        secondCollection.setShareProfitPanelId(secondCollectionConfig.getShareProfitPanelId());
        secondCollection.setOffShelfTime(DateUtil.endOfDay(secondCollection.getOnShelfTime()));
        secondCollection.setSalesTime(new Date());
        secondCollection.setCollectionSumCount(digitalCollection.getSumCount());
        secondCollection.setNumbering(userCollection.getNumbering());
        secondCollection.setSalesPrice(buyPrice);
        secondCollection.setCharge(secondCollectionConfig.getCharge().multiply(buyPrice));
        if (BooleanUtil.isTrue(userCollection.getAntiHoardFlag())) {
            secondCollection.setAntiHoardPrice(userCollection.getAntiHoardPrice());
        } else {
            secondCollection.setAntiHoardPrice(BigDecimal.ZERO);
        }
        secondCollection.setMinPrice(secondCollectionConfig.getMinPrice());
        secondCollection.setMaxPrice(secondCollectionConfig.getMaxPrice());
        secondCollection.setMarketType(secondCollectionConfig.getMarketType());
        secondCollection.setCreateId(UserPool.getUser().getId());
        secondCollectionDao.save(secondCollection);
        userCollectionDao.setConsignStatus(userCollectionId, CollectionOnConsignEnum.ON_SALES);
        if (secondCollectionConfig.getMarketType() == MarketTypeEnum.FREE_MARKET) {
            messageQueueHelper.sendMessage(MessageTopic.FREE_MARKET_TOPIC, secondCollection);
        } else if (secondCollectionConfig.getMarketType() == MarketTypeEnum.BRAND_INCUBATION) {
            String key = RedisKeyEnum.SECOND_SALES_COLLECTION.getKey() + secondCollection.getCollectionId().toString();
            redisTemplate.opsForList().rightPush(key, secondCollection.getId().toString());
            redisTemplate.expire(key, getTodayEndSecond(), TimeUnit.SECONDS);
        }
        return Boolean.TRUE;

    }


    private long getTodayEndSecond() {
        DateTime now = DateTime.now();
        DateTime end = DateUtil.endOfDay(now);
        return DateUtil.between(now, end, DateUnit.SECOND);
    }


    @Override
    public Integer commodityPurchaseRestriction(UserInfo userInfo, SecondCollectionConfig secondCollectionConfig) {
        Boolean isTeamIncomeByUserId = filterIncomeListService.getIsTeamIncomeByUserId(userInfo.getId());
        if (!isTeamIncomeByUserId) {
            return -1;
        }

        if (ObjectUtil.isNull(secondCollectionConfig)) {
            throw new GlobalRunTimeException("藏品已无法购买购买");
        }
        if (!secondCollectionConfig.getStatus()) {
            throw new GlobalRunTimeException("该藏品暂未上架");
        }
        // 可购买的商品数量
        Integer buyShares = secondCollectionConfig.getBuyShares();
        // 如果购买数量为0,则不限制购买数量
        if (buyShares == 0) {
            return -1;
        }
        int countByCollectionIdAndUserId = userCollectionDao.getCountByCollectionIdAndUserId(secondCollectionConfig.getCollectionId(), userInfo.getId());
        return buyShares - countByCollectionIdAndUserId;
    }

    @Override
    public GetUserConsignmentVO getCollectionConsignment(Long collection) {
        UserCollection userCollection = userCollectionDao.getById(collection);
        if (BeanUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException("用户不拥有该藏品");
        }
        if (!userCollection.getIsHold()) {
            throw new GlobalRunTimeException("用户不拥有该藏品");
        }
        GetUserConsignmentVO getUserConsignmentVO = new GetUserConsignmentVO();
        // 藏品
        DigitalCollection digitalCollection = digitalCollectionDao.getById(userCollection.getCollectionId());
        if (BeanUtil.isEmpty(digitalCollection)) {
            throw new GlobalRunTimeException("藏品不存在");
        }
        // 藏品配置
        SecondCollectionConfig byCollectionId = secondCollectionConfigDao.getByCollectionId(userCollection.getCollectionId());
        if (BeanUtil.isEmpty(byCollectionId)) {
            throw new GlobalRunTimeException("藏品禁止上架");
        }
        if (!byCollectionId.getStatus()) {
            throw new GlobalRunTimeException("藏品禁止上架");
        }
        if (BeanUtil.isEmpty(byCollectionId)) {
            getUserConsignmentVO.setPriceFloor(BigDecimal.ZERO);
        } else {
            getUserConsignmentVO.setPriceFloor(byCollectionId.getStartPrice());
        }
// 获取排除今天的历史最高价.
        BigDecimal maxPriceByCollectionId = freeMarketHistoricalMaximumAmount(byCollectionId.getCollectionId());
// maxPriceByCollectionId历史最大值如果为空 那么startPrice=startPrice  如果不为空 ,那么判定maxPriceByCollectionId>startPrice 那么startPrice=maxPriceByCollectionId
        BigDecimal floatingPrice = maxPriceByCollectionId == null ? byCollectionId.getStartPrice() : maxPriceByCollectionId.compareTo(byCollectionId.getStartPrice()) == 1 ? maxPriceByCollectionId : byCollectionId.getStartPrice();
        getUserConsignmentVO.setMinPrice(byCollectionId.getMinPrice());
        getUserConsignmentVO.setMaxPrice(byCollectionId.getMaxPrice());
        if (digitalCollection.getCollectionType() == DigitalMarketTypeEnum.ECOLOGY) {
            ExitConsensusUser exitConsensusUser = exitConsensusUserDao.getByUserId(UserPool.getUser().getId());
            if (ObjectUtil.isNotNull(exitConsensusUser) && exitConsensusUser.getStatus()) {
                //pass
            } else {
                getUserConsignmentVO.setMinPrice(byCollectionId.getConsensusMinPrice());
                getUserConsignmentVO.setMaxPrice(byCollectionId.getConsensusMaxPrice());
            }
        }
        getUserConsignmentVO.setSalePrice(digitalCollection.getIssuePrice());
        getUserConsignmentVO.setBuyPrice(userCollection.getBuyPrice());
        getUserConsignmentVO.setLatestPrice(floatingPrice);
        getUserConsignmentVO.setFirstTitle(digitalCollection.getFirstTitle());
        getUserConsignmentVO.setCreationContent(digitalCollection.getCreationContent());
        getUserConsignmentVO.setNewDeal(digitalCollection.getNewDeal());
        return getUserConsignmentVO;
    }

    @Override
    public Boolean getUserOrderExist(Long userId) {
        return secondOrderDao.getUserOrderExist(userId);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrderById(Long orderId, UserInfo user) {
        SecondOrder secondOrder = secondOrderDao.getById(orderId);
        Assert.notNull(secondOrder, () -> new GlobalRunTimeException("订单不存在"));


        Assert.isTrue(secondOrder.getBuyUserId().longValue() == user.getId().longValue(), () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
        Assert.isFalse(secondOrder.getStatus() != OrderStatusEnum.WAIT_PAY, () -> new GlobalRunTimeException("订单状态不正确"));
        cancelOrderById(secondOrder.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrderById(Long orderId) {
        SecondOrder secondOrder = secondOrderDao.getById(orderId);
        if (secondOrder.getStatus() != OrderStatusEnum.WAIT_PAY) {
            log.warn("关闭订单失败:{}", secondOrder.getOrderNo());
            return;
        }
        Assert.isTrue(secondOrderDao.cancelOrderByOrderId(secondOrder.getId()), () -> new GlobalRunTimeException(ErrorCode.LATER_TRY));
        Assert.isTrue(secondCollectionDao.cancelOrder(secondOrder.getSecondCollectionId()), () -> new GlobalRunTimeException(ErrorCode.LATER_TRY));
        if (secondOrder.getMarketType() == MarketTypeEnum.BRAND_INCUBATION) {
            redisTemplate.opsForList().leftPush(RedisKeyEnum.SECOND_SALES_COLLECTION.getKey() + secondOrder.getCollectionId().toString(), secondOrder.getSecondCollectionId().toString());
        } else if (secondOrder.getMarketType() == MarketTypeEnum.FREE_MARKET) {
            updateCacheMinPrice(secondOrder.getCollectionId());
        }
    }

    @Override
    public Page<MyConsignmentListVO> myConsignmentList(UserInfo user, Integer pageNo, Integer pageSize) {
        Page<MyConsignmentListVO> page = secondCollectionDao.myConsignmentList(new Page<>(pageNo, pageSize), user.getId());
        for (MyConsignmentListVO record : page.getRecords()) {
            record.setIsLockOrder(secondOrderDao.isLockOrderBySecondCollectionId(record.getSecondCollectionId()));
        }

        List<MyConsignmentListVO> collect = page.getRecords().stream().filter(o -> o.getIsLockOrder() == Boolean.TRUE).collect(Collectors.toList());
        List<MyConsignmentListVO> list = page.getRecords().stream().filter(o -> o.getIsLockOrder() == Boolean.FALSE).collect(Collectors.toList());
        list.addAll(collect);
        page.setRecords(list);
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveBatchCancellationConsignment(SaveBatchCancellationConsignmentDTO saveBatchCancellationConsignmentDTO) {
        saveBatchCancellationConsignmentDTO.getList().forEach(secondCollectionId -> {
            CancellationConsignmentDTO cancellationConsignmentDTO = new CancellationConsignmentDTO();
            cancellationConsignmentDTO.setId(secondCollectionId);
            cancellationConsignmentDTO.setDealPwd(saveBatchCancellationConsignmentDTO.getDealPwd());
            cancellationConsignment(cancellationConsignmentDTO);
        });
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paySuccess(List<SecondOrder> secondOrders) {
        String lockKey = RedisKeyEnum.SECOND_USER_LOCK.getKey() + secondOrders.get(0).getBuyUserId();
        redisTemplate.delete(lockKey);
        for (SecondOrder secondOrder : secondOrders) {
            buyWithThird(secondOrder);
        }
        if (secondOrders.get(0).getIsConsensus()) {
            userConsensusService.adjustConsensusService(secondOrders.get(0).getBuyUserId(), secondOrders.get(0).getCollectionId(), BigDecimal.valueOf(secondOrders.size()), UserConsensusTypeEnums.BUY, secondOrders.get(0).getFirstTitle(), null);
        }
    }

    public void buyWithThird(SecondOrder secondOrder) {
        Assert.notNull(secondOrder, () -> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
        Assert.isTrue(secondOrder.getStatus() == OrderStatusEnum.WAIT_PAY, () -> new GlobalRunTimeException(ErrorCode.ORDER_STATUS_ERROR));
        SecondCollection secondCollection = secondCollectionDao.getById(secondOrder.getSecondCollectionId());
        Assert.isFalse(secondOrder.getBuyUserId().longValue() == secondCollection.getUserId().longValue(), () -> new GlobalRunTimeException(ErrorCode.CANT_BUY_SELF));
        Assert.notNull(secondCollection, () -> new GlobalRunTimeException(ErrorCode.PRODUCT_NOT_FOUND));
        Assert.isTrue(secondCollection.getStatus() == ConSignStatus.LOCK, () -> new GlobalRunTimeException(ErrorCode.PRODUCT_NOT_FOUND));
        UserWallet userWallet = userWalletService.getByUserId(secondOrder.getBuyUserId());
        if (BeanUtil.isEmpty(secondOrder)) {
            throw new GlobalRunTimeException("订单已过期");
        }

        secondOrder.setStatus(OrderStatusEnum.PAYMENT);
        secondOrder.setBuyPayBalancePrice(BigDecimal.ZERO);
        secondOrder.setPayTime(new Date());
//        secondOrder.updateById();
        secondOrderDao.updateById(secondOrder);
        //修改用户为用效用户
        UserInfo userInfo = userInfoDao.getById(secondOrder.getBuyUserId());
        if (!userInfo.getIsValid()) {
            userInfoDao.setIsValid(userInfo.getId());
            messageQueueHelper.sendMessage(MessageTopic.USER_FIRST_BUY, new UserFirstBuyDTO(userInfo.getId(), secondOrder.getId(), 2));

        }
        //藏品转移
        userCollectionService.buy(secondOrder);
        secondCollection.setStatus(ConSignStatus.SUCCESS);
        secondCollection.setSalesTime(DateTime.now());
        secondCollectionDao.updateById(secondCollection);

        //添加二级交易的业绩
//        userInfoDao.addSecondaryHoldToken(userInfo.getId(), secondOrder.getBuyPrice());
        messageQueueHelper.sendMessage(MessageTopic.SECOND_ORDER_TOPIC, secondOrder);
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                MetaMapSettleDTO metaMapSettleDTO = new MetaMapSettleDTO();
                MetaMapSettleDTO order = metaMapSettleDTO.order(secondOrder.getOrderNo(), secondOrder.getBuyUserId(), MetaMapSettleSourceTypeEnum.SECOND_ORDER, secondOrder.getBuyPrice(), secondOrder.getCharge(), secondOrder.getFirstTitle(), secondOrder.getShareProfitPanelId(), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                messageQueueHelper.sendMessage(MessageTopic.META_MAP_SETTLE, order, MessageTopic.META_MAP_SETTLE, secondOrder.getOrderNo());
            }
        });

    }

    @Override
    public SellCollectionPriceDataVO sellCollectionPriceData(Long collectionId) {
        SellCollectionPriceDataVO sellCollectionPriceDataVO = new SellCollectionPriceDataVO();
        // 藏品
        DigitalCollection digitalCollection = digitalCollectionDao.getById(collectionId);
        if (BeanUtil.isEmpty(digitalCollection)) {
            throw new GlobalRunTimeException("藏品不存在");
        }
        // 藏品配置
        SecondCollectionConfig byCollectionId = secondCollectionConfigDao.getByCollectionId(collectionId);
        if (BeanUtil.isEmpty(byCollectionId)) {
            throw new GlobalRunTimeException("藏品禁止上架");
        }
        if (!byCollectionId.getStatus()) {
            throw new GlobalRunTimeException("配置不存在");
        }
        sellCollectionPriceDataVO.setCreationContent(digitalCollection.getCreationContent());
        sellCollectionPriceDataVO.setFirstTitle(digitalCollection.getFirstTitle());
        sellCollectionPriceDataVO.setMaxPrice(byCollectionId.getMaxPrice());
        return sellCollectionPriceDataVO;
    }

    @Override
    public BigDecimal orderNotPayPrice(OrderNotPayPriceDTO orderNotPayPriceDTO) {
        if (CollUtil.isEmpty(orderNotPayPriceDTO.getList())) {
            throw new GlobalRunTimeException("请求参数不存在");
        }
        BigDecimal totalMoney = secondOrderDao.orderNotPayPrice(orderNotPayPriceDTO.getList());
        return totalMoney != null ? totalMoney.setScale(2, BigDecimal.ROUND_DOWN) : Convert.toBigDecimal("0.00");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean daoFreeMarketHitShelf(Long userCollectionId, BigDecimal buyPrice, String dealPwd, Long daoId) {
        UserCollection userCollection = userCollectionDao.selectByIdAndUserIdAndIsHold(userCollectionId, UserPool.getUser().getId());
        DigitalCollection digitalCollection = digitalCollectionDao.getById(userCollection.getCollectionId());

        if (!digitalCollection.getUserCreatorId().equals(daoId)) {
            throw new GlobalRunTimeException("非该DAO藏品，需前往APP操作寄售");
        }
        freeMarketHitShelf(userCollectionId, buyPrice, dealPwd);
        return true;
    }

    @Override
    public Map startTime(MarketTypeEnum marketType) {
        Map map = new HashedMap();
        StaticData staticData = staticDataService.getByType(marketType == MarketTypeEnum.BRAND_INCUBATION ? "market_config" : "free_market_config");
        MarketConfigDTO marketConfigDTO = JSONObject.parseObject(staticData.getValue(), MarketConfigDTO.class);
        DateTime now = DateTime.now();
        String dateStr = now.toString("yyyy-MM-dd");
        DateTime buyStartDate1 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBuyStartTimeOne(), "yyyy-MM-dd HH:mm");
        DateTime buyEndDate1 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBuyEndTimeOne(), "yyyy-MM-dd HH:mm");
        DateTime buyStartDate2 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBuyStartTimeTwo(), "yyyy-MM-dd HH:mm");
        DateTime buyEndDate2 = DateUtil.parse(dateStr + " " + marketConfigDTO.getBuyEndTimeTwo(), "yyyy-MM-dd HH:mm");
        if (!((now.after(buyStartDate1) && now.before(buyEndDate1)) || (now.after(buyStartDate2) && now.before(buyEndDate2)))) {
            if (now.before(buyStartDate1)) {
                map.put("time", buyStartDate1.getTime() - now.getTime());
            }
            if (now.after(buyStartDate1) && now.before(buyStartDate2)) {
                map.put("time", buyStartDate2.getTime() - now.getTime());
            } else if (now.after(buyEndDate2)) {
                DateTime dateTime = DateUtil.offsetDay(buyStartDate1, 1);
                map.put("time", dateTime.getTime() - now.getTime());
            }
            map.put("isStart", Boolean.FALSE);
            return map;
        }
        map.put("time", 0L);
        map.put("isStart", Boolean.TRUE);
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LockOrderVO lockBrandOrder(UserInfo userInfo, SecondBrandCollectionLockOrderDTO request) {
        Map map = startTime(MarketTypeEnum.BRAND_INCUBATION);
        Boolean isStart = (Boolean) map.get("isStart");
        Assert.isTrue(isStart, () -> new GlobalRunTimeException("当前非市场交易时间段"));
        SecondCollectionConfig collectionConfig = secondCollectionConfigDao.getByCollectionId(request.getCollectionId());
        Assert.isTrue(collectionConfig.getStatus(), () -> new GlobalRunTimeException(ErrorCode.PRODUCT_HAS_BEEN_DESCONTINUED));

        LockOrderVO lockOrderVO;
        RLock userLock = redisson.getLock(RedisKeyEnum.BRAND_USER_BUY_LOCK.getKey() + userInfo.getId());
        try {
            boolean getUserLock = userLock.tryLock(5, TimeUnit.SECONDS);
            if (getUserLock) {
                lockOrderVO = chooseLockType(collectionConfig, userInfo, request.getCollectionId(), request.getBuyCount());
            } else {
                throw new GlobalRunTimeException(ErrorCode.NO_FREQUENTLY_OPERATION);
            }
        } catch (InterruptedException e) {
            throw new GlobalRunTimeException(ErrorCode.LOCK_FAIL_RETRY);
        } finally {
            userLock.unlock();
        }
        return lockOrderVO;
    }

    @Override
    public Page<MySalestListVO> mySalestList(UserInfo user, Integer pageNo, Integer pageSize) {
        return secondCollectionDao.mySalestList(new Page<>(pageNo, pageSize), user.getId());
    }

    @Override
    public List<MySalestListVO> maintainSalestList(UserInfo user, Long collectionId, BigDecimal lowPrice, BigDecimal highPrice) {
        return secondCollectionDao.maintainSalestList(user.getId(), collectionId, lowPrice, highPrice);
    }

    /**
     * 处理订单操作
     *
     * @param secondCollectionId 2级的寄售id
     * @param secondOrder        订单对象
     */
    public void order(UserInfo userInfo, Long secondCollectionId, SecondOrder secondOrder, MarketTypeEnum marketType, String orderNo, List<Long> mallLockId, Boolean isConsensus) {
        SecondCollection secondCollection = secondCollectionDao.getById(secondCollectionId);
        Long collectionId = secondCollection.getCollectionId();
        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionId(collectionId);
        if (BeanUtil.isEmpty(secondCollectionConfig) || !secondCollectionConfig.getStatus()) {
            throw new GlobalRunTimeException("藏品已下架自由市场");
        }

        if (BeanUtil.isEmpty(secondCollection)) {
            mallLockId.add(secondCollectionId);
            return;
        }
        ConSignStatus conSignStatus = secondCollection.getStatus();

        if (secondCollection.getUserId().equals(userInfo.getId())) {
            throw new GlobalRunTimeException("无法购买自己上架的藏品");
        }
        // 当前藏品非寄售中
        if (conSignStatus.getCode() != 1) {
            mallLockId.add(secondCollectionId);
            return;
        }
        DigitalCollection digitalCollection = digitalCollectionDao.getById(secondCollection.getCollectionId());
        // 寄售类型不匹配
        if (secondCollection.getMarketType() != marketType) {
            UserCollection userCollection = userCollectionDao.getById(secondCollectionId);
            throw new ModelException(StrUtil.format("藏品编号{}/{}不存在", userCollection.getNumbering(), digitalCollection.getSumCount()), ErrorCode.PRODUCT_NOT_FOUND);
        }
        SecondOrder dataIsExist = secondOrderDao.selectBySecondCollectionId(secondCollectionId);
        if (!BeanUtil.isEmpty(dataIsExist)) {
            // 判定是否已经支付
            OrderStatusEnum status = dataIsExist.getStatus();
            // 已支付订单
            if (status.getCode() == 2) {
                mallLockId.add(secondCollectionId);
                return;
            }
            // 已创建订单时间
            Date createTime = dataIsExist.getCreateTime();
            // 当前时间
            Date now = new Date();
            // 偏移1秒  防止数据库datetime类型中,程序毫秒级超过500就会进位导致锁不住的问题.
            now = DateUtil.offsetSecond(now, 1);
            // 偏移3分钟后的时间
            DateTime dateTime = DateUtil.offsetMinute(createTime, 3);
            // 未支付已创建订单
            if (status.getCode() == 1 && (createTime.before(now) || createTime.equals(now)) && (dateTime.after(now) || dateTime.equals(now))) {
                mallLockId.add(secondCollectionId);
                return;
//                throw new GlobalRunTimeException(ErrorCode.GOODS_ORDER_LOCK);
            }
        }
        secondOrder.setUserCollectionId(digitalCollection.getUserCreatorId());
        secondOrder.setFirstTitle(digitalCollection.getFirstTitle());
        secondOrder.setCollectionSumCount(digitalCollection.getSumCount());
        secondOrder.setNumbering(secondCollection.getNumbering());
        secondOrder.setSecondCollectionId(secondCollection.getId());
        secondOrder.setCollectionId(secondCollection.getCollectionId());
        secondOrder.setUserCollectionId(secondCollection.getUserCollectionId());
        secondOrder.setSalesUserId(secondCollection.getUserId());
        secondOrder.setIsConsensus(isConsensus);
        secondOrder.setBuyUserId(userInfo.getId());
        secondOrder.setShareProfitPanelId(secondCollection.getShareProfitPanelId());
        secondOrder.setBuyPrice(secondCollection.getSalesPrice());
        // 如果挂方和买方都是市值账号的话,那么,把手续费设置为0.只收取gas费.
        DigitalCollection counterKnock = digitalCollectionDao.getById(collectionId);
        if (filterIncomeListDao.checkIsFilterAccount(counterKnock.getUserCreatorId(), userInfo.getId())
                && filterIncomeListDao.checkIsFilterAccount(counterKnock.getUserCreatorId(), secondOrder.getSalesUserId())) {
            secondOrder.setCharge(BigDecimal.ZERO);
        } else {
            secondOrder.setCharge(secondCollection.getCharge());
        }
        secondOrder.setGas(secondCollectionConfig.getGas());
        secondOrder.setCloseTime(DateUtil.offsetMinute(new Date(), 3));

//        if (MarketTypeEnum.FREE_MARKET == secondCollection.getMarketType()) {//自由市场
//            DaoDivideInfo divideInfo = daoDivideInfoDao.getDivideInfoByDaoId(digitalCollection.getUserCreatorId());
//            if (ObjectUtil.isNotNull(divideInfo) && divideInfo.getStatus()) {                //并且开启了分成
//                if (filterIncomeListDao.checkIsFilterAccount(digitalCollection.getUserCreatorId(), secondOrder.getSalesUserId()) &&
//                        filterIncomeListDao.checkIsFilterAccount(digitalCollection.getUserCreatorId(), secondOrder.getBuyUserId())) {//确认是市值对敲
//                    secondOrder.setCharge(divideInfo.getMintPrice());
//                } else { //手续费返点
//
//                    //手续费的一半
//                    BigDecimal divide = secondCollection.getCharge().divide(BigDecimal.valueOf(2), 8, BigDecimal.ROUND_DOWN);
//                    //手续费的一半减去上链费
//                    BigDecimal subtract = divide.subtract(divideInfo.getMintPrice());
//                    //返点金额
//                    BigDecimal returnPrice = subtract.multiply(divideInfo.getShareRatio().movePointLeft(2));
//
//                    //如果返点金额大于0 并且 大于最低返点金额
//                    if(NumberUtil.isGreater(divide,BigDecimal.ZERO) && NumberUtil.isGreater(divide,divideInfo.getMintPrice())){
//                        BigDecimal multiply = divideInfo.getMintPrice().multiply(divideInfo.getShareRatio().movePointLeft(2));
//                        BigDecimal charge = divide.subtract(multiply).setScale(2,BigDecimal.ROUND_DOWN);
//
//                        //如果最后金额大于0 则返点 否则平台全收
//                        if(NumberUtil.isGreater(charge,BigDecimal.ZERO)){
//                            userWalletService.addIncome(divideInfo.getReturnUserId(), secondOrder.getOrderNo(), charge, BigDecimal.ZERO, WalletDetailTypeEnum.DAO_CHARGE_SHARE, ExpenditureRecordTypeEnum.CHARGE_RETURN, "自由市场{" + digitalCollection.getFirstTitle() + "}");
//                        }
//                    }
//                }
//            }
//        }
        secondOrder.setStatus(OrderStatusEnum.WAIT_PAY);
        secondOrder.setOrderNo(orderNo);
        secondOrder.setDealTime(DateTime.now());
        // 二级市场的全部都给钱.
        secondOrder.setPreventHoard(BigDecimal.ZERO);
        secondOrder.setMarketType(marketType);
        // 增加偏移3分钟的偏移量  增加时间 2023-11-28
        secondOrder.setCloseTime(DateUtil.offsetMinute(secondOrder.getDealTime(), 3));
        secondOrder.setSettleFlag(false);
        secondOrder.setPerformanceSettleFlag(secondOrder.getSettleFlag());
        secondOrder.setRealAmount(secondOrder.getBuyPrice().subtract(secondOrder.getCharge()).subtract(secondCollectionConfig.getGas()));
//        secondOrder.insert();
        secondOrderDao.save(secondOrder);
        secondCollection.setStatus(ConSignStatus.LOCK);
        secondCollectionDao.updateById(secondCollection);
        if (secondCollection.getMarketType() == MarketTypeEnum.BRAND_INCUBATION) {
            redisTemplate.opsForList().remove(RedisKeyEnum.SECOND_SALES_COLLECTION.getKey() + secondCollection.getCollectionId().toString(), 1, secondCollection.getId().toString());
        }
    }


    /**
     * 孵化区下单
     *
     * @param secondCollectionId 2级的寄售id
     */
    public void orderBrand(UserInfo userInfo, Long secondCollectionId, DigitalCollection digitalCollection, LockOrderVO lockOrderVO) {
        SecondCollection secondCollection = secondCollectionDao.getById(secondCollectionId);
        if (MarketTypeEnum.FREE_MARKET == secondCollection.getMarketType()) {
            return;
        }
        if (secondCollection.getUserId().equals(userInfo.getId())) {
            return;
        }
        // 当前藏品非寄售中
        if (secondCollection.getStatus() != ConSignStatus.ON_SALES) {
            return;
        }
        SecondOrder dataIsExist = secondOrderDao.selectBySecondCollectionId(secondCollectionId);
        if (ObjectUtil.isNotNull(dataIsExist)) {
            return;
        }

        SecondOrder secondOrder = new SecondOrder();

        secondOrder.setUserCollectionId(secondCollection.getUserCollectionId());
        secondOrder.setFirstTitle(digitalCollection.getFirstTitle());
        secondOrder.setCollectionSumCount(digitalCollection.getSumCount());
        secondOrder.setNumbering(secondCollection.getNumbering());
        secondOrder.setSecondCollectionId(secondCollection.getId());
        secondOrder.setCollectionId(secondCollection.getCollectionId());
        secondOrder.setUserCollectionId(secondCollection.getUserCollectionId());
        secondOrder.setSalesUserId(secondCollection.getUserId());
        secondOrder.setBuyUserId(userInfo.getId());
        secondOrder.setShareProfitPanelId(secondCollection.getShareProfitPanelId());
        secondOrder.setBuyPrice(secondCollection.getSalesPrice());
        secondOrder.setCharge(secondCollection.getCharge());
        secondOrder.setCloseTime(lockOrderVO.getExpirationTime());
        secondOrder.setStatus(OrderStatusEnum.WAIT_PAY);
        secondOrder.setOrderNo(OrderNoUtil.getOrderNo());
        secondOrder.setDealTime(lockOrderVO.getNowDateSourceType());
        secondOrder.setPreventHoard(BigDecimal.ZERO);
        secondOrder.setMarketType(secondCollection.getMarketType());
        secondOrder.setSettleFlag(false);
        secondOrder.setPerformanceSettleFlag(secondOrder.getSettleFlag());
        // 判定防囤罚没金额
        if (secondCollection.getAntiHoardPrice() != null && secondCollection.getAntiHoardPrice().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal realPrice = secondCollection.getSalesPrice().subtract(secondCollection.getCharge());
            if (secondCollection.getAntiHoardPrice().compareTo(realPrice) < 0) {
                secondOrder.setPreventHoard(realPrice.subtract(secondCollection.getAntiHoardPrice()));
            }
        }
        secondOrder.setRealAmount(secondOrder.getBuyPrice().subtract(secondOrder.getCharge()).subtract(secondOrder.getPreventHoard()));
//        secondOrder.insert();
        secondOrderDao.save(secondOrder);
        Assert.isTrue(secondCollectionDao.lockOrder(secondOrder.getSecondCollectionId()), () -> new GlobalRunTimeException("尝试锁单失败，请重试"));
        lockOrderVO.addMoney(secondOrder.getBuyPrice());
        lockOrderVO.getOrderIds().add(secondOrder.getId());
        BrandOrderListVO brandOrderListVO = new BrandOrderListVO();
        brandOrderListVO.setId(secondOrder.getId());
        brandOrderListVO.setNumbering(secondOrder.getNumbering());
        brandOrderListVO.setMoney(secondOrder.getBuyPrice());
        brandOrderListVO.setOrderNo(secondOrder.getOrderNo());
        brandOrderListVO.setSecondCollectionId(secondCollectionId);
        lockOrderVO.getOrderList().add(brandOrderListVO);
    }

    private LockOrderVO chooseLockType(SecondCollectionConfig collectionConfig, UserInfo userInfo, Long collectionId, Integer buyCount) {
        LockOrderVO lockOrderVO = lockWithCache(collectionConfig, userInfo, collectionId, buyCount);
        DigitalCollection digitalCollection = digitalCollectionDao.getById(collectionId);

        if (ObjectUtil.isNotNull(lockOrderVO)) {
            lockOrderVO.setSumCount(digitalCollection.getSumCount());
            return lockOrderVO;
        } else {
            LockOrderVO notCacheCollection = lockWithDB(collectionConfig, userInfo, collectionId, buyCount);
            notCacheCollection.setSumCount(digitalCollection.getSumCount());
            return notCacheCollection;
        }
    }

    private LockOrderVO lockWithCache(SecondCollectionConfig collectionConfig, UserInfo userInfo, Long collectionId, Integer buyCount) {
        List<Long> brandSecondCollectionIdsWithCache = getBrandSecondCollectionIdsWithCache(collectionConfig, userInfo, collectionId, buyCount);
        if (CollUtil.isEmpty(brandSecondCollectionIdsWithCache)) {
            return null;
        }
        List<Long> failLock = Lists.newArrayList();
        List<RLock> lock = new ArrayList();
        try {
            // 用来存放被锁的id
            brandSecondCollectionIdsWithCache.forEach(secondCollectionId -> {
                String key = StrUtil.format("LOCK_ORDER:{}", secondCollectionId);
                RLock orderLock = redissonClient.getLock(key);
                boolean heldByCurrentThread = orderLock.tryLock();
                if (heldByCurrentThread) {
                    lock.add(orderLock);
                } else {
                    failLock.add(secondCollectionId);
                }
            });
            if (CollUtil.isNotEmpty(failLock)) {
                brandSecondCollectionIdsWithCache.removeAll(failLock);
            }
            if (CollUtil.isEmpty(brandSecondCollectionIdsWithCache)) {
                throw new GlobalRunTimeException(ErrorCode.LOCK_FAIL_RETRY);
            }
            return lockBrandOrder(userInfo, collectionId, brandSecondCollectionIdsWithCache);
        } finally {
            // 批量释放锁
            lock.forEach(rLock -> {
                rLock.unlock();
            });
        }
    }

    private LockOrderVO lockWithDB(SecondCollectionConfig collectionConfig, UserInfo userInfo, Long collectionId, Integer buyCount) {
        RLock collectionLock = redisson.getLock(RedisKeyEnum.BRAND_COLLECTION_BUY_LOCK.getKey() + collectionId.toString());
        List<Long> failLock = Lists.newArrayList();
        try {
            boolean getCollectionLock = collectionLock.tryLock(3, TimeUnit.SECONDS);
            if (getCollectionLock) {
                List<Long> brandSecondCollectionIdsWithDB = getBrandSecondCollectionIdsWithDB(collectionConfig, userInfo, collectionId, buyCount);
                if (CollUtil.isNotEmpty(brandSecondCollectionIdsWithDB)) {
                    List<RLock> lock = new ArrayList();
                    try {
                        // 用来存放被锁的id
                        brandSecondCollectionIdsWithDB.forEach(secondCollectionId -> {
                            String key = StrUtil.format("LOCK_ORDER:{}", secondCollectionId);
                            RLock orderLock = redissonClient.getLock(key);
                            boolean heldByCurrentThread = orderLock.tryLock();
                            if (heldByCurrentThread) {
                                lock.add(orderLock);
                            } else {
                                failLock.add(secondCollectionId);
                            }
                        });
                        if (CollUtil.isNotEmpty(failLock)) {
                            brandSecondCollectionIdsWithDB.removeAll(failLock);
                        }
                        if (CollUtil.isEmpty(brandSecondCollectionIdsWithDB)) {
                            throw new GlobalRunTimeException("尝试锁单失败，请重试");
                        }
                        return lockBrandOrder(userInfo, collectionId, brandSecondCollectionIdsWithDB);
                    } finally {
                        // 批量释放锁
                        lock.forEach(rLock -> {
                            rLock.unlock();
                        });
                    }
                }
            } else {
                throw new GlobalRunTimeException("尝试锁单失败，请重试");
            }
        } catch (InterruptedException e) {
            throw new GlobalRunTimeException("尝试锁单失败，请重试");
        } finally {
            collectionLock.unlock();
        }
        throw new GlobalRunTimeException("尝试锁单失败，请重试");
    }


    public void updateCacheMinPrice(Long collectionId) {
        BigDecimal collectionLowestPrice = secondCollectionMapper.getCollectionLowestPrice(collectionId);
        if (ObjectUtil.isNotNull(collectionLowestPrice)) {
            String key = RedisKeyEnum.FREE_MARKET_LOWEST_PRICE.getKey() + collectionId;
            redisTemplate.opsForValue().set(key, collectionLowestPrice.setScale(2).toPlainString(), 2, TimeUnit.MINUTES);
        }
    }

    @Override
    public String getCacheMinPrice(Long collectionId) {
        String key = RedisKeyEnum.FREE_MARKET_LOWEST_PRICE.getKey() + collectionId;
        Object o = redisTemplate.opsForValue().get(key);
        if (ObjectUtil.isNull(o)) {
            BigDecimal collectionLowestPrice = secondCollectionDao.getCollectionLowestPrice(collectionId);
            if (ObjectUtil.isNull(collectionLowestPrice)) {
                return BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
            }
            redisTemplate.opsForValue().set(key, collectionLowestPrice.setScale(2, BigDecimal.ROUND_DOWN).toPlainString(), 2, TimeUnit.MINUTES);
            o = collectionLowestPrice.setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
        }
        if (ObjectUtil.isNull(o)) {
            return null;
        }
        return String.valueOf(o);
    }

    @Override
    public String getCacheMinPriceForConsensus(Long collectionId) {
        String key = RedisKeyEnum.FREE_MARKET_LOWEST_CONSENSUS_PRICE.getKey() + collectionId;
        Object o = redisTemplate.opsForValue().get(key);
        if (ObjectUtil.isNull(o)) {
            BigDecimal collectionLowestPrice = secondCollectionDao.getCollectionLowestPriceForConsensus(collectionId);
            if (ObjectUtil.isNull(collectionLowestPrice)) {
                return BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
            }
            redisTemplate.opsForValue().set(key, collectionLowestPrice.setScale(2, BigDecimal.ROUND_DOWN).toPlainString(), 2, TimeUnit.MINUTES);
            o = collectionLowestPrice.setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
        }
        if (ObjectUtil.isNull(o)) {
            return null;
        }
        return String.valueOf(o);
    }

    @Override
    public String getCacheMinPriceNotInConsensus(Long collectionId) {
        String key = RedisKeyEnum.FREE_MARKET_LOWEST_PRICE.getKey() + collectionId;
        Object o = redisTemplate.opsForValue().get(key);
        if (ObjectUtil.isNull(o)) {
            BigDecimal collectionLowestPrice = secondCollectionDao.getCollectionLowestPriceNotInConsensus(collectionId);
            if (ObjectUtil.isNull(collectionLowestPrice)) {
                return BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
            }
            redisTemplate.opsForValue().set(key, collectionLowestPrice.setScale(2, BigDecimal.ROUND_DOWN).toPlainString(), 3, TimeUnit.MINUTES);
            o = collectionLowestPrice.setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
        }
        if (ObjectUtil.isNull(o)) {
            return null;
        }
        return String.valueOf(o);
    }

}
